package fun.ticsmyc.rpc.client.transport.netty.handler;

import fun.ticsmyc.rpc.client.transport.netty.CompletableFutureHelper;
import fun.ticsmyc.rpc.client.transport.netty.RpcRequestSenderFactory;
import fun.ticsmyc.rpc.common.entity.RpcRequest;
import fun.ticsmyc.rpc.common.entity.RpcResponse;
import fun.ticsmyc.rpc.common.factory.SingletonFactory;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;

/**
 * @author Ticsmyc
 * @date 2020-10-23 21:18
 */
public class NettyClientHandler extends SimpleChannelInboundHandler<RpcResponse> {

    private static final Logger logger = LoggerFactory.getLogger(NettyClientHandler.class);

    private final CompletableFutureHelper completableFutureHelper  = SingletonFactory.getSingletonInstance(CompletableFutureHelper.class);

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RpcResponse msg) throws Exception {
        logger.debug("客户端收到响应：{}",msg);
        completableFutureHelper.complete(msg);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        logger.error("处理过程调用返回消息时发生异常");
        cause.printStackTrace();
        ctx.close();
    }


    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if(evt instanceof IdleStateEvent){
            //心跳事件
            IdleStateEvent idleStateEvent = (IdleStateEvent)evt;
            if(idleStateEvent.state() == IdleState.WRITER_IDLE){
                //5s不写了
                logger.info("客户端发送心跳包[{}]",ctx.channel().remoteAddress());
                RpcRequest rpcRequest = new RpcRequest();
                rpcRequest.setHeartBeat(true);
                RpcRequestSenderFactory.getRpcRequestSender((InetSocketAddress)ctx.channel().remoteAddress());
                ctx.writeAndFlush(rpcRequest).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
            }
        }else{
            super.userEventTriggered(ctx,evt);
        }
    }
}
